package sunbao.ido.support;


import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import sunbao.ido.factory.IDoFactoryBean;
import sunbao.ido.stereotype.IDo;

import java.util.Iterator;
import java.util.Set;

/**
 * \* User: MeiZhongHao
 * \* Date: 2018-10-23
 * \* Time: 12:26
 * \* Description:
 * \
 */
public class ClassPathIDoScanner extends ClassPathBeanDefinitionScanner {

    private IDoFactoryBean<?> iDoFactoryBean = new IDoFactoryBean();

    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
        if (!beanDefinitions.isEmpty()) {
            this.processBeanDefinitions(beanDefinitions);
        }
        return beanDefinitions;
    }

    private void processBeanDefinitions(Set<BeanDefinitionHolder> beanDefinitions) {
        Iterator var3 = beanDefinitions.iterator();
        while (var3.hasNext()) {
            BeanDefinitionHolder holder = (BeanDefinitionHolder) var3.next();
            GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
            // 设置 iDoFactoryBean 默认的构造函数入参 ： 即Class<T> mapperInterface
            // 放在definition.setBeanClass 后面执行, definition.getBeanClassName()的值就会变成iDoFactoryBean
            // 所以应先执行addGenericArgumentValue
            definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());

            definition.setBeanClass(this.iDoFactoryBean.getClass());

        }
    }

    public ClassPathIDoScanner(BeanDefinitionRegistry registry) {
        super(registry, false);
    }

    /**
     * 注册 过滤器
     */
    public void registerTypeFilter() {
        this.addIncludeFilter(new AnnotationTypeFilter(IDo.class));
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return beanDefinition.getMetadata().isInterface() && beanDefinition.getMetadata().isIndependent();
    }

    public void setiDoFactoryBean(IDoFactoryBean<?> iDoFactoryBean) {
        this.iDoFactoryBean = iDoFactoryBean != null ? iDoFactoryBean : new IDoFactoryBean();
    }
}